package com.xxkj.drugtraceability.base
import com.xxkj.drugtraceability.net.Result
import com.google.gson.JsonParseException
import com.xxhis.refactor.eventbus.MessageCode
import com.xxkj.drugtraceability.bean.EventMessage
import com.xxkj.drugtraceability.net.WanResponse
import com.xxkj.drugtraceability.utils.CommonUtils.checkNetworkStatus
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.coroutineScope
import org.greenrobot.eventbus.EventBus
import retrofit2.HttpException
import java.io.IOException
import java.net.*

open class BaseRepository() {
    suspend fun <T : Any> apiCall(call: suspend () -> WanResponse<T>): WanResponse<T> {
        return call.invoke()
    }

    suspend fun <T : Any> safeApiCall(call: suspend () -> Result<T>): Result<T> {
        return try {
            call()
        } catch (e: Exception) {
            // An exception was thrown when calling the API so we're converting this to an IOException
//            EventBus.getDefault().post(EventMessage(MsgUtils.getMsg("msgyd09198","网络连接失败"), NET_ERROR_FOR_TTS))
            when (e) {
                is SocketTimeoutException -> Result.Error(SocketTimeoutException(checkNetworkStatus()))
                is UnknownHostException -> Result.Error(UnknownHostException(checkNetworkStatus()))
                is HttpException -> Result.Error(UnknownHostException(checkNetworkStatus()))
                is ConnectException -> Result.Error(UnknownHostException(checkNetworkStatus()))
                is JsonParseException -> Result.Error(JsonParseException("数据解析出错，请重试"))
                is IOException -> Result.Error(e)
                is NullPointerException -> Result.Error(IOException("数据空引用错误", e))
                is IndexOutOfBoundsException-> Result.Error(IOException("角标越界异常", e))
                else -> Result.Error(e)
            }
        }
    }

    suspend fun <T : Any?> executeResponse(response: WanResponse<T>, successBlock: (suspend CoroutineScope.() -> Unit)? = null,
                                           errorBlock: (suspend CoroutineScope.() -> Unit)? = null): Result<T> {
        return coroutineScope {
            if (response.code != "200") {
                if (response.code == "401"){
                    EventBus.getDefault().post(EventMessage(response.msg, MessageCode.NEED_LOGIN))
                    Result.Login
                }else{
                    errorBlock?.let { it() }
                    Result.Error(IOException(response.msg), response.msg,code = response.code.toInt())
                }
            } else {
                successBlock?.let { it() }
                Result.Success(response.data,response.msg)
            }
        }
    }
}